package com.syyo.admin.common.security.config;

import io.jsonwebtoken.*;
import io.jsonwebtoken.io.Decoders;
import io.jsonwebtoken.security.Keys;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.security.Key;
import java.util.Arrays;
import java.util.Collection;
import java.util.Date;
import java.util.stream.Collectors;

/**
 * @author /
 *  token处理对象
 */
@Slf4j
@Component
public class TokenProvider implements InitializingBean {

   private final SecurityProperties properties;//security配置类
   private static final String AUTHORITIES_KEY = "auth";//权限的key值
   private Key key;

   public TokenProvider(SecurityProperties properties) {
      this.properties = properties;
   }


   @Override
   public void afterPropertiesSet() {
      //启动项目时，自动生成key
      byte[] keyBytes = Decoders.BASE64.decode(properties.getBase64Secret());
      this.key = Keys.hmacShaKeyFor(keyBytes);
   }

   /**
    * 创建token
    * @param authentication security上下文对象
    * @return
    */
   public String createToken(Authentication authentication) {
      String authorities = authentication.getAuthorities().stream()
         .map(GrantedAuthority::getAuthority)
         .collect(Collectors.joining(","));

      //过期时间
      long now = (new Date()).getTime();
      Date validity = new Date(now + properties.getTokenValidityInSeconds());

      return Jwts.builder()
              .setSubject(authentication.getName())//用户名
              .claim(AUTHORITIES_KEY, authorities)//权限字符串
              .signWith(key, SignatureAlgorithm.HS256)//使用加密
              .setExpiration(validity)//过期时间
              .compact();

   }

   /**
    * 解析token拿到Authentication上下文对象
    * @param token
    * @return
    */
   public Authentication getAuthentication(String token) {
      Claims claims = Jwts.parser()
         .setSigningKey(key)
         .parseClaimsJws(token)
         .getBody();

      Collection<? extends GrantedAuthority> authorities =
         Arrays.stream(claims.get(AUTHORITIES_KEY).toString().split(","))
            .map(SimpleGrantedAuthority::new)
            .collect(Collectors.toList());

      User principal = new User(claims.getSubject(), "", authorities);
       return new UsernamePasswordAuthenticationToken(principal, token, authorities);
   }

    /**
     * 校验token
     * @param authToken
     * @return
     */
   boolean validateToken(String authToken) {
      try {
         Jwts.parser().setSigningKey(key).parseClaimsJws(authToken);
         return true;
      } catch (io.jsonwebtoken.security.SecurityException | MalformedJwtException e) {
         log.info("无效的token");
      } catch (ExpiredJwtException e) {
         log.info("token令牌过期");
      } catch (UnsupportedJwtException e) {
         log.info("不支持jwt令牌");
      } catch (IllegalArgumentException e) {
         log.info("处理程序的jwt令牌压缩无效");
      }
      return false;
   }

    /**
     * 获取token
     * @param request
     * @return
     */
   public String getToken(HttpServletRequest request){
       //获取token头
      final String requestHeader = request.getHeader(properties.getHeader());
      // "Bearer " 处理token值的头部
      if (requestHeader != null && requestHeader.startsWith(properties.getTokenStartWith())) {
         return requestHeader.substring(7);
      }
      return null;
   }
}
